#include "glare.gles2.GpuBuffer.h"
#include "glare.gles2.GpuResourceFactory.h"
#include "glare.gles2.Driver.h"

namespace Glare {
	
	GLES2GpuBuffer::GLES2GpuBuffer(GLES2GpuResourceFactory* factory, const GpuBufferDescription& description)
		: GpuBuffer(description)
		, _factory(factory)
	{
		// TODO: bind buffer to GLES2GpuResourceFactory (like Ogre does for RenderSystem)
		glGenBuffers(1, &_gl_buffer_id);
		EGL_CHECK_ERROR;
	}

	GLES2GpuBuffer::~GLES2GpuBuffer()
	{
		// TODO: unbind buffer from GLES2GpuResourceFactory (like Ogre does for RenderSystem)
		glDeleteBuffers(1, &_gl_buffer_id);
		EGL_CHECK_ERROR;
	}

	GpuResource::Interface* GLES2GpuBuffer::_GetInterface()
	{
		return this;
	}

	GpuResourceFactory* GLES2GpuBuffer::GetFactory() const
	{
		return _factory;
	}

	const GLuint& GLES2GpuBuffer::GetGLES2Id() const
	{
		return _gl_buffer_id;
	}

	void GLES2GpuBuffer::_UpdateImpl(const uint& dest_sub_resource, Box* dest_box, const void* src_data, const uint& src_row_pitch, const uint& src_depth_pitch)
	{
		const GpuBufferDescription& desc = GetDescription();

		GLenum mode = GL_STATIC_DRAW;

		GLenum buffer_mode = GL_NONE;

		// TODO: a way to update a buffer without binding it to the pipeline ???
		if (desc.BindFlags & GpuResourceBind::VertexBuffer)
			buffer_mode = GL_ARRAY_BUFFER;

		if (desc.BindFlags & GpuResourceBind::IndexBuffer)
			buffer_mode = GL_ELEMENT_ARRAY_BUFFER;

		if (buffer_mode == GL_NONE)
			return;

		// TODO: save the currently bound buffer, so we can restore it

		glBindBuffer(buffer_mode, _gl_buffer_id);
		glBufferData(
			buffer_mode,
			desc.ElementCount * desc.ElementSize,
			src_data,
			mode);
		EGL_CHECK_ERROR;

		// TODO: restore the previously bound buffer
	}
}
